package processingHandling;

import java.io.BufferedReader;
import java.io.Console;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import outputAdapters.OutputAdapterFactory;
import dataModifiers.ModifierFactory;
import inputs.InputFactory;
import management.ApplicationManager;
import management.MidiManager;
import management.UDPManager;
import management.UpdateManager;
import midi.MidiOutParameterFactory;
import processing.core.PApplet;

/**
 * Abstract class to encapsulate a Processing Applet.
 * Allows us to contain a Processing Applet, but add default functionality
 * such as Input/Modifier/Midi handling and set up. This way, each Applet
 * we implement can depend on this default functionality and not have to
 * be rewritten each time.
 * 
 * @author Dylan James
 *
 */
public abstract class PAppletWrapper extends PApplet{
	
	// Managers - Accessible from child classes
	protected ApplicationManager TheApplicationManager;
	protected UpdateManager TheUpdateManager;
	protected MidiManager TheMidiManager;
	protected UDPManager TheUDPManager;
	
	// Factories - Accessible from child classes
	protected InputFactory TheInputFactory;
	protected ModifierFactory TheModifierFactory;
	protected OutputAdapterFactory TheOutputAdapterFactory;
	protected MidiOutParameterFactory TheMidiOutParameterFactory;
	
	protected Socket StepperBeeManagerSocket;
	protected PrintStream StepperBeeManagerOutputStream;
	protected DataInputStream StepperBeeManagerInputStream;
	protected BufferedReader StepperBeeManagerInputReader;
	
	private int count = 0;
	
	/**
	 * Processing Applet setup function.
	 * Sets up the managers and factories.
	 * Then calls the concrete Wrapper implementations setup function.
	 */
	public void setup(){
		// Get all the managers.
		TheApplicationManager = ApplicationManager.getApplicationManager();
		// Set this as the Application Managers PApplet.
		TheApplicationManager.setPApplet(this);
		
		TheUpdateManager = UpdateManager.getUpdateManager();
		TheMidiManager = MidiManager.getMidiManager();
		TheUDPManager = UDPManager.getUDPManager();
		
		// Get all the factories.
		TheInputFactory = InputFactory.getFactory();
		TheModifierFactory = ModifierFactory.getFactory();
		TheOutputAdapterFactory = OutputAdapterFactory.getFactory();
		TheMidiOutParameterFactory = MidiOutParameterFactory.getFactory();
		
		TheUDPManager.send("JavaApp Opening");
		
		this.WrapperSetup();
	}
	
	/**
	 * Processing Applet draw function.
	 * Calls the concrete Wrapper implementations draw function.
	 */
	public void draw(){
//		if (count == 30)
//		{
//			TheMidiManager.Mute();
//		}
//		
//		if (count == 60)
//		{
//			TheMidiManager.Unmute();
//			count = 0;
//		}
//		
//		count++;
		
		String recStr = TheUDPManager.receive();
		
		if (recStr.equals("MUTE"))
		{
			TheMidiManager.Mute();
			System.out.println("MUTED");
		}
		
		if (recStr.equals("UNMUTE"))
		{
			TheMidiManager.Unmute();
			System.out.print("UNMUTED");
		}
		
		
		TheUpdateManager.Update();
		this.WrapperDraw();
		TheUpdateManager.Invalidate();
	}
	
	/**
	 * Setup function called at Applet creation.
	 * Implement setup procedure here.
	 */
	public abstract void WrapperSetup();
	/**
	 * Draw function called each frame.
	 * Implement draw procedure here.
	 */
	public abstract void WrapperDraw();
	
	/**
	 * Gets the colorVal at the given pixel.
	 * This returns a processing colorVal - use GetRed/GetGreen/GetBlue to get integer
	 * values for the corresponding colors
	 * 
	 * @param x The x coordinate of the pixel to get
	 * @param y The y coordinate of the pixel to get
	 * @return The colorVal at the given pixel.
	 */
	public int GetPixel(int x, int y){
		return get(x, y);
	}
	
	/**
	 * Gets the red value from a given colorVal
	 * 
	 * @param colorVal colorVal to get from
	 * @return The red value from the given colorVal
	 */
	public int GetRed(int colorVal){
		return (int)red(colorVal);
	}
	
	/**
	 * Gets the green value from a given colorVal
	 * 
	 * @param colorVal colorVal to get from
	 * @return The green value from the given colorVal
	 */
	public int GetGreen(int colorVal){
		return (int)green(colorVal);
	}
	
	/**
	 * Gets the blue value from a given colorVal
	 * 
	 * @param colorVal colorVal to get from
	 * @return The blue value from the given colorVal
	 */
	public int GetBlue(int colorVal){
		return (int)blue(colorVal);
	}
	
	
	
}
